// Inspired by KF5 KColorCombo, published under LGPLv2

#include "brushstylecombobox.h"

#include <QAbstractItemDelegate>
#include <QApplication>
#include <QStylePainter>

class BrushStyleComboDelegate : public QAbstractItemDelegate
{
public:
    enum
    {
        BrushStyleRole = Qt::UserRole + 1
    };

    enum LayoutMetrics
    {
        FrameMargin = 3
    };

    explicit BrushStyleComboDelegate(QObject *parent = 0):
        QAbstractItemDelegate(parent)
    {

    }

    virtual ~BrushStyleComboDelegate()
    {

    }

    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        // highlight selected item
        QStyleOptionViewItem opt(option);
        opt.showDecorationSelected = true;
        QStyle *style = opt.widget ? opt.widget->style() : QApplication::style();
        style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
        QRect innerrect = option.rect.adjusted(FrameMargin, FrameMargin, -FrameMargin, -FrameMargin);

        // inner color
        const QColor color = option.palette.color(QPalette::Text);
        painter->setPen(Qt::transparent);
        painter->setBrush(QBrush(color, index.data(BrushStyleRole).value<Qt::BrushStyle>()));
        painter->setRenderHint(QPainter::Antialiasing, true);
        painter->drawRoundedRect(innerrect, 2, 2);
        painter->setRenderHint(QPainter::Antialiasing, false);
        painter->setPen(color);
        painter->setBrush(Qt::NoBrush);
        painter->drawRoundedRect(innerrect, 2, 2);
    }

    virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        Q_UNUSED(index)

        // the width does not matter, as the view will always use the maximum width available
        return QSize(100, option.fontMetrics.height() + 2 * FrameMargin);
    }
};

BrushStyleComboBox::BrushStyleComboBox(QWidget *parent):
    QComboBox(parent)
{
    setItemDelegate(new BrushStyleComboDelegate(this));

    connect(this, QOverload<int>::of(&QComboBox::activated),
            this, &BrushStyleComboBox::onActivated);
    connect(this, QOverload<int>::of(&QComboBox::highlighted),
            this, &BrushStyleComboBox::onHighlighted);
    connect(this, QOverload<int>::of(&QComboBox::currentIndexChanged),
            this, &BrushStyleComboBox::onCurrentIndexChanged);
}

BrushStyleComboBox::~BrushStyleComboBox()
{

}

void BrushStyleComboBox::setCurrentBrushStyle(Qt::BrushStyle style)
{
    setCurrentIndex(m_brushStyleList.indexOf(style));
}

Qt::BrushStyle BrushStyleComboBox::currentBrushStyle() const
{
    return m_brushStyleList.value(currentIndex());
}

void BrushStyleComboBox::setBrushStyles(const QList<Qt::BrushStyle> &styles)
{
    clear();
    m_brushStyleList = styles;
    for (int index=0; index<m_brushStyleList.count(); index++)
    {
        addItem(QString());
        setItemData(index,
                    QVariant::fromValue<Qt::BrushStyle>(m_brushStyleList.value(index)),
                    BrushStyleComboDelegate::BrushStyleRole);
    }
}

QList<Qt::BrushStyle> BrushStyleComboBox::brushStyles() const
{
    return m_brushStyleList;
}

void BrushStyleComboBox::onActivated(int index)
{
    emit activated(m_brushStyleList.value(index));
}

void BrushStyleComboBox::onHighlighted(int index)
{
    m_paintedBrushStyle = m_brushStyleList.value(index);
    emit highlighted(m_paintedBrushStyle);
}

void BrushStyleComboBox::onCurrentIndexChanged(int index)
{
    m_paintedBrushStyle = m_brushStyleList.value(index);
    emit currentBrushStyleChanged(m_paintedBrushStyle);
}

void BrushStyleComboBox::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QStylePainter painter(this);
    painter.setPen(palette().color(QPalette::Text));

    QStyleOptionComboBox option;
    initStyleOption(&option);
    painter.drawComplexControl(QStyle::CC_ComboBox, option);


    QRect frame = style()->subControlRect(QStyle::CC_ComboBox, &option,
                                          QStyle::SC_ComboBoxEditField, this).adjusted(1, 1, -1, -1);
    const QColor color = option.palette.color(QPalette::Text);
    painter.setPen(Qt::transparent);
    painter.setBrush(QBrush(color, m_paintedBrushStyle));
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.drawRoundedRect(frame, 2, 2);
    painter.setRenderHint(QPainter::Antialiasing, false);
    painter.setPen(color);
    painter.setBrush(Qt::NoBrush);
    painter.drawRoundedRect(frame, 2, 2);
}
